//+------------------------------------------------------------------+
//|                                    Advanced_BollingerRSI_EA.mq5 |
//|                        基于布林带+RSI的多因子智能交易EA             |
//|                   参考TradingView布林带指标进行MQL5实现            |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, 金融量化专家"
#property link      "https://www.mql5.com"
#property version   "3.00"
#property description "多因子结合的布林带+RSI交易EA，参考TradingView策略"

#include <Trade\Trade.mqh>
#include <Trade\PositionInfo.mqh>

//--- 输入参数
input group "=== 布林带参数 ==="
input int                InpBB_Length = 20;                    // 布林带长度
input double             InpBB_StdDev = 2.0;                   // 标准差倍数
input ENUM_APPLIED_PRICE InpBB_Source = PRICE_CLOSE;           // 数据源

input group "=== RSI参数 ==="
input bool               InpUseRSI = true;                     // 启用RSI过滤
input int                InpRSI_Period = 14;                   // RSI周期
input double             InpRSI_OverBought = 70.0;             // RSI超买水平
input double             InpRSI_OverSold = 30.0;               // RSI超卖水平

input group "=== 资金管理 ==="
input double             InpFixed_Lot = 0.1;                   // 固定手数
input bool               InpUse_RiskManagement = false;        // 使用风险管理
input double             InpRisk_Percent = 2.0;                // 风险百分比

input group "=== 止损止盈 ==="
input bool               InpUse_FixedSLTP = true;              // 使用ATR动态止损止盈
input double             InpATR_SL_Multiplier = 2.0;           // ATR止损倍数
input double             InpATR_TP_Multiplier = 3.0;           // ATR止盈倍数
input int                InpATR_Period = 14;                   // ATR周期

input group "=== 出场管理 ==="
input bool               InpExit_BB_Middle = true;             // 中轨出场

input group "=== 其他设置 ==="
input int                InpMagic_Number = 999888;             // 魔术号
input string             InpComment = "BB+RSI_MultiFactor";     // 订单注释
input bool               InpTrade_OnNewBar = true;             // 仅新K线交易

//--- 全局变量
CTrade         m_trade;
CPositionInfo  m_position;

int            h_Bands;               // 布林带句柄
int            h_RSI;                 // RSI句柄
int            h_ATR;                 // ATR句柄
datetime       m_last_bar_time;      // 上一根K线时间
double         m_point;              // 点值

//+------------------------------------------------------------------+
//| 专家初始化函数                                                   |
//+------------------------------------------------------------------+
int OnInit()
{
    // 设置交易类
    m_trade.SetExpertMagicNumber(InpMagic_Number);
    m_trade.SetDeviationInPoints(10);
    
    // 初始化品种信息
    m_point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
    
    // 打印品种信息
    Print("📊 品种信息：", _Symbol);
    Print("   点值：", m_point);
    Print("   最小止损距离：", SymbolInfoInteger(_Symbol, SYMBOL_TRADE_STOPS_LEVEL), " 点");
    
    // 创建布林带指标
    h_Bands = iBands(_Symbol, PERIOD_CURRENT, InpBB_Length, 0, InpBB_StdDev, InpBB_Source);
    if(h_Bands == INVALID_HANDLE)
    {
        Print("创建布林带指标失败，错误码：", GetLastError());
        return INIT_FAILED;
    }
    
    // 创建RSI指标
    if(InpUseRSI)
    {
        h_RSI = iRSI(_Symbol, PERIOD_CURRENT, InpRSI_Period, PRICE_CLOSE);
        if(h_RSI == INVALID_HANDLE)
        {
            Print("创建RSI指标失败，错误码：", GetLastError());
            return INIT_FAILED;
        }
    }
    
    // 创建ATR指标
    h_ATR = iATR(_Symbol, PERIOD_CURRENT, InpATR_Period);
    if(h_ATR == INVALID_HANDLE)
    {
        Print("创建ATR指标失败，错误码：", GetLastError());
        return INIT_FAILED;
    }
    
    // 初始化时间
    m_last_bar_time = iTime(_Symbol, PERIOD_CURRENT, 0);
    
    Print("✅ 多因子布林带+RSI EA初始化成功");
    return INIT_SUCCEEDED;
}

//+------------------------------------------------------------------+
//| 专家去初始化函数                                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
    if(h_Bands != INVALID_HANDLE) IndicatorRelease(h_Bands);
    if(h_RSI != INVALID_HANDLE) IndicatorRelease(h_RSI);
    if(h_ATR != INVALID_HANDLE) IndicatorRelease(h_ATR);
    Print("EA已卸载，原因代码：", reason);
}

//+------------------------------------------------------------------+
//| 主要执行函数                                                     |
//+------------------------------------------------------------------+
void OnTick()
{
    // 新K线检查
    if(InpTrade_OnNewBar)
    {
        datetime current_time = iTime(_Symbol, PERIOD_CURRENT, 0);
        if(current_time == m_last_bar_time) return;
        m_last_bar_time = current_time;
    }
    
    // 检查当前持仓状态
    bool has_position = false;
    ENUM_POSITION_TYPE position_type = WRONG_VALUE;
    
    if(m_position.Select(_Symbol) && m_position.Magic() == InpMagic_Number)
    {
        has_position = true;
        position_type = m_position.PositionType();
    }
    
    // 如果有持仓，检查出场条件
    if(has_position)
    {
        CheckExitSignals(position_type);
        return;
    }
    
    // 检查入场信号
    CheckEntrySignals();
}

//+------------------------------------------------------------------+
//| 多因子入场信号检查                                               |
//+------------------------------------------------------------------+
void CheckEntrySignals()
{
    // 获取布林带数据
    double bb_upper[], bb_middle[], bb_lower[];
    if(!GetBollingerBands(bb_upper, bb_middle, bb_lower, 5)) return;
    
    // 获取RSI数据
    double rsi_current = 50.0;
    if(InpUseRSI && !GetRSIValue(rsi_current)) return;
    
    // 获取价格数据
    double close_1 = iClose(_Symbol, PERIOD_CURRENT, 1);
    double close_2 = iClose(_Symbol, PERIOD_CURRENT, 2);
    double close_3 = iClose(_Symbol, PERIOD_CURRENT, 3);
    double high_1 = iHigh(_Symbol, PERIOD_CURRENT, 1);
    double low_1 = iLow(_Symbol, PERIOD_CURRENT, 1);
    
    bool buy_signal = false;
    bool sell_signal = false;
    string reason = "";
    
    //=== 多因子结合策略 ===
    
    // 因子1: 布林带位置判断
    bool bb_buy_condition = close_1 > bb_middle[1];  // 价格在中轨上方
    bool bb_sell_condition = close_1 < bb_middle[1]; // 价格在中轨下方
    
    // 因子2: 布林带宽度判断（波动性）
    double bb_width = bb_upper[1] - bb_lower[1];
    double bb_width_avg = (bb_upper[2] + bb_upper[3] + bb_upper[4]) / 3 - (bb_lower[2] + bb_lower[3] + bb_lower[4]) / 3;
    bool volatility_ok = bb_width > bb_width_avg * 0.8; // 波动性足够
    
    // 因子3: 价格动量判断
    bool momentum_buy = close_1 > close_2 && close_2 > close_3;  // 连续上涨
    bool momentum_sell = close_1 < close_2 && close_2 < close_3; // 连续下跌
    
    // 因子4: 布林带突破/反弹判断
    bool breakout_buy = close_1 > bb_upper[1] && close_2 <= bb_upper[2];  // 突破上轨
    bool breakout_sell = close_1 < bb_lower[1] && close_2 >= bb_lower[2]; // 突破下轨
    bool bounce_buy = low_1 <= bb_lower[1] && close_1 > bb_lower[1];      // 下轨反弹
    bool bounce_sell = high_1 >= bb_upper[1] && close_1 < bb_upper[1];    // 上轨回落
    
    // 因子5: RSI过滤
    bool rsi_buy_ok = !InpUseRSI || (rsi_current < InpRSI_OverBought && rsi_current > 30);
    bool rsi_sell_ok = !InpUseRSI || (rsi_current > InpRSI_OverSold && rsi_current < 70);
    
    //=== 买入信号组合 ===
    if(bb_buy_condition && volatility_ok && rsi_buy_ok)
    {
        // 策略1: 突破上轨 + 动量确认
        if(breakout_buy && momentum_buy)
        {
            buy_signal = true;
            reason = "突破上轨+动量确认";
        }
        // 策略2: 中轨上方 + 动量确认 + RSI支持
        else if(momentum_buy && rsi_current > 40 && rsi_current < 65)
        {
            buy_signal = true;
            reason = "中轨上方+动量+RSI支持";
        }
    }
    
    //=== 卖出信号组合 ===
    if(bb_sell_condition && volatility_ok && rsi_sell_ok)
    {
        // 策略1: 突破下轨 + 动量确认
        if(breakout_sell && momentum_sell)
        {
            sell_signal = true;
            reason = "突破下轨+动量确认";
        }
        // 策略2: 中轨下方 + 动量确认 + RSI支持
        else if(momentum_sell && rsi_current < 60 && rsi_current > 35)
        {
            sell_signal = true;
            reason = "中轨下方+动量+RSI支持";
        }
    }
    
    // 打印详细分析信息
    if(buy_signal || sell_signal)
    {
        Print("🔍 多因子信号分析：");
        Print("   布林带位置：", bb_buy_condition ? "中轨上方" : "中轨下方");
        Print("   波动性：", volatility_ok ? "足够" : "不足");
        Print("   动量：", momentum_buy ? "上涨" : (momentum_sell ? "下跌" : "横盘"));
        Print("   突破：", breakout_buy ? "上轨突破" : (breakout_sell ? "下轨突破" : "无"));
        Print("   反弹：", bounce_buy ? "下轨反弹" : (bounce_sell ? "上轨回落" : "无"));
        Print("   RSI：", DoubleToString(rsi_current, 2));
    }
    
    // 执行交易
    if(buy_signal) ExecuteBuyOrder(reason);
    if(sell_signal) ExecuteSellOrder(reason);
}

//+------------------------------------------------------------------+
//| 检查出场信号                                                     |
//+------------------------------------------------------------------+
void CheckExitSignals(ENUM_POSITION_TYPE pos_type)
{
    // 获取布林带数据
    double bb_upper[], bb_middle[], bb_lower[];
    if(!GetBollingerBands(bb_upper, bb_middle, bb_lower, 3)) return;
    
    // 获取RSI数据
    double rsi_current = 50.0;
    if(InpUseRSI) 
    {
        double rsi[];
        ArraySetAsSeries(rsi, true);
        if(CopyBuffer(h_RSI, 0, 0, 1, rsi) >= 1)
        {
            rsi_current = rsi[0];
        }
    }
    
    bool should_close = false;
    string close_reason = "";
    
    double current_price = (pos_type == POSITION_TYPE_BUY) ? SymbolInfoDouble(_Symbol, SYMBOL_BID) : SymbolInfoDouble(_Symbol, SYMBOL_ASK);
    
    // 打印调试信息
    Print("🔍 出场检查 - 当前价格：", current_price, "，中轨：", bb_middle[0]);
    
    //--- 布林带中轨出场
    if(InpExit_BB_Middle)
    {
        if(pos_type == POSITION_TYPE_BUY && current_price <= bb_middle[0])
        {
            should_close = true;
            close_reason = "价格回到中轨(多头) - 价格:" + DoubleToString(current_price, 5) + " 中轨:" + DoubleToString(bb_middle[0], 5);
        }
        else if(pos_type == POSITION_TYPE_SELL && current_price >= bb_middle[0])
        {
            should_close = true;
            close_reason = "价格回到中轨(空头) - 价格:" + DoubleToString(current_price, 5) + " 中轨:" + DoubleToString(bb_middle[0], 5);
        }
    }
    
    //--- RSI出场
    if(InpUseRSI && !should_close)
    {
        if(pos_type == POSITION_TYPE_BUY && rsi_current >= InpRSI_OverBought)
        {
            should_close = true;
            close_reason = "RSI超买出场";
        }
        else if(pos_type == POSITION_TYPE_SELL && rsi_current <= InpRSI_OverSold)
        {
            should_close = true;
            close_reason = "RSI超卖出场";
        }
    }
    
    // 执行平仓
    if(should_close)
    {
        if(m_trade.PositionClose(_Symbol))
        {
            Print("✅ 仓位已平仓：", close_reason);
        }
        else
        {
            Print("❌ 平仓失败：", m_trade.ResultComment());
        }
    }
}

//+------------------------------------------------------------------+
//| 获取布林带数据                                                   |
//+------------------------------------------------------------------+
bool GetBollingerBands(double &upper[], double &middle[], double &lower[], int count)
{
    ArraySetAsSeries(upper, true);
    ArraySetAsSeries(middle, true);
    ArraySetAsSeries(lower, true);
    
    if(CopyBuffer(h_Bands, 1, 0, count, upper) < count ||
       CopyBuffer(h_Bands, 0, 0, count, middle) < count ||
       CopyBuffer(h_Bands, 2, 0, count, lower) < count)
    {
        Print("获取布林带数据失败");
        return false;
    }
    
    return true;
}

//+------------------------------------------------------------------+
//| 获取RSI数值                                                      |
//+------------------------------------------------------------------+
bool GetRSIValue(double &rsi_value)
{
    double rsi[];
    ArraySetAsSeries(rsi, true);
    
    if(CopyBuffer(h_RSI, 0, 0, 2, rsi) < 2)
    {
        Print("获取RSI数据失败");
        return false;
    }
    
    rsi_value = rsi[1];  // 使用完成的K线
    return true;
}

//+------------------------------------------------------------------+
//| 获取ATR数值                                                      |
//+------------------------------------------------------------------+
double GetATRValue()
{
    double atr[];
    ArraySetAsSeries(atr, true);
    
    if(CopyBuffer(h_ATR, 0, 0, 1, atr) < 1)
    {
        Print("获取ATR数据失败");
        return 0;
    }
    
    return atr[0];
}

//+------------------------------------------------------------------+
//| 计算手数                                                         |
//+------------------------------------------------------------------+
double CalculateLotSize()
{
    if(!InpUse_RiskManagement) return InpFixed_Lot;
    
    double balance = AccountInfoDouble(ACCOUNT_BALANCE);
    double risk_amount = balance * InpRisk_Percent / 100.0;
    double point_value = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE);
    double sl_points = InpUse_FixedSLTP ? InpATR_SL_Multiplier : 1.0;
    double lot_size = risk_amount / (sl_points * point_value);
    
    // 规范化手数
    double min_lot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
    double max_lot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);
    double lot_step = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);
    
    lot_size = MathMax(min_lot, MathMin(max_lot, lot_size));
    lot_size = MathFloor(lot_size / lot_step) * lot_step;
    
    return lot_size;
}

//+------------------------------------------------------------------+
//| 执行买入订单                                                     |
//+------------------------------------------------------------------+
void ExecuteBuyOrder(string reason)
{
    double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
    double sl = 0, tp = 0;
    
    if(InpUse_FixedSLTP)
    {
        double atr_value = GetATRValue();
        if(atr_value > 0)
        {
            sl = ask - InpATR_SL_Multiplier * atr_value;
            tp = ask + InpATR_TP_Multiplier * atr_value;
        }
        else
        {
            sl = ask - 100 * m_point;
            tp = ask + 200 * m_point;
        }
    }
    
    double lot_size = CalculateLotSize();
    string comment = InpComment + " Buy-" + reason;
    
    if(m_trade.Buy(lot_size, _Symbol, ask, sl, tp, comment))
    {
        Print("✅ 买入成功：", lot_size, " 手，价格：", ask, "，原因：", reason);
    }
    else
    {
        Print("❌ 买入失败：", m_trade.ResultComment());
    }
}

//+------------------------------------------------------------------+
//| 执行卖出订单                                                     |
//+------------------------------------------------------------------+
void ExecuteSellOrder(string reason)
{
    double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
    double sl = 0, tp = 0;
    
    if(InpUse_FixedSLTP)
    {
        double atr_value = GetATRValue();
        if(atr_value > 0)
        {
            sl = bid + InpATR_SL_Multiplier * atr_value;
            tp = bid - InpATR_TP_Multiplier * atr_value;
        }
        else
        {
            sl = bid + 100 * m_point;
            tp = bid - 200 * m_point;
        }
    }
    
    double lot_size = CalculateLotSize();
    string comment = InpComment + " Sell-" + reason;
    
    if(m_trade.Sell(lot_size, _Symbol, bid, sl, tp, comment))
    {
        Print("✅ 卖出成功：", lot_size, " 手，价格：", bid, "，原因：", reason);
    }
    else
    {
        Print("❌ 卖出失败：", m_trade.ResultComment());
    }
} 